home *** CD-ROM | disk | FTP | other *** search
- ;--------------------------------------------------------------------------
- ;------------------------------- 26TIME v1.0 ----------------------------
- ;--------------------------------------------------------------------------
- ;
- ; PROGRAM 26TIME
- ; VERSION 1.1
- ; AUTHOR PETER NELSON
- ;
- ; DESCRIPTION:
- ;
- ; This program is designed for use with the IBM-CGA card. It resets the
- ; 6485 chip to display 26 instead of the normal 25 rows of text on the
- ; screen. On the 26th line is displayed the time, updated 1nc per minute.
- ; It is theoretically possible to use this program with a normal graphics
- ; card. You would have to put the time in the upper right corner, and check
- ; 18 times/second to see if it had scrolled off the screen yet. If it had,
- ; you would have to redisplay it. This program checks twice/second the
- ; the color of the lower-right character of the screen. It then prints the
- ; 26th row that color, and displays the time using that color too. This
- ; makes it look good no matter what program you are running. If the color
- ; of the lower-right character changes, it redraws the entire bottom line,
- ; including the time. Every time the time is displayed, there is a quiet
- ; "tick" sound made. It is possible to have the seconds being displayed
- ; as they change, or have the colon flash once/second, but I decided this
- ; would eat up too much processor power.
- ;
- ;
- ; REVISIONS:
- ;
- ; VERSION # AUTHOR DESCRIPTION
- ;
- ; 1.1 Peter Nelson Some programs would blank the screen by
- ; a hardware method that also ended up blanking
- ; my time display. Added a check to see if
- ; the last position on the 26th line had an
- ; 'm'. If not, I redisplayed. This makes it
- ; compatible with Lotus-123.
- ;
- ;------------------------------ INCLUDES --------------------------------
-
- include \asm\macros.asm ; defines the IFR macro
- include \asm\equates.asm ; has many generally used values equated
-
- ;------------------------------ PUBLICS ---------------------------------
- ;
- ; The public directive allows the use of these labels by the symbolic
- ; debugger (SYMDEB).
-
-
- public start, begin, setvectors, int18_routine, int18_cont1, exit
- public checkrow, check_cont0, check_cont1, checkrow_exit
- public checkrow_exit_fine, checkrow_exit, showtime, show_cont1, show_cont2
- public show_cont3, showtime_exit, conv, convloop, conv_cont1, conv_exit
- public showword, showbyte, shownib, show_c1, display_al, click, veryend
- public checkrow_ret, checkrow_exit_reshow
-
- public intvector, counter1, convtable, hours, mins, secs, count, message
- public counter1, counter2, screen_page, attribute, flag
-
-
- ;------------------------------ SEGMENT ---------------------------------
-
- code segment ; It must orginate at 0100h
- assume ds:code, cs:code, es:code ; or else it can't be a .COM
- org 0100h ; file and mem-resident.
-
- ;------------------------------- START ----------------------------------
-
- start: ; make sure DS=CS and jump around data
- push cs
- pop ds
- jmp begin
-
- ;------------------------------- DATA -----------------------------------
- ;
- ; Be sure to use the CS: override for all the data in this program
- ; since this is a memory resident routine, and we can't be sure of the
- ; state of the [ds] register.
-
-
- intvector dw 0 ; This defines two words (a doubleword) to hold
- dw 0 ; the address of the old timer routine.
- counter1 dw 0 ; A counter for determining when check bottom line
- counter2 dw 0 ; Another counter for determining when to display
- attribute db 0 ; Stores the screen attribute of the lower line
- screen_page db 0 ; stores the screen page being viewed
- mode db 0 ; stores the screen mode we are in
- flag db 0 ; indicates a redisplay is neccessary
- hours db 00 ; stores the hours
- mins db 00 ; stores the minutes
- secs db 00 ; stores the seconds
- count dw 0000 ; stores the count of seconds since midnight
- dw 0000
-
- message db cr,lf,cr,lf,cr,lf
- db ' 26TIME Version 1.1',cr,lf,cr,lf
- db 'This program was written in MASM 4.0 by Peter Nelson. It is a memory',cr,lf
- db 'resident program that occupies 1.2 k-bytes (1264) of ram. The current time',cr,lf
- db 'will be displayed on the 26th line of the screen at all times. It will not',cr,lf
- db 'interfere with graphing. It will work only with the IBM-CGA card and',cr,lf
- db 'compatibles (including compaq).',cr,lf,cr,lf,'$'
-
- convtable db 01h,02h,04h,08h,016h,032h,064h ; used for bin-dec convert
-
-
-
- ;------------------------------ PROGRAM ---------------------------------
-
- begin:
- mov ah, 9 ; display logo
- mov dx, offset message
- int msdos
-
- setvectors:
- mov ah, 035h ; use DOS interrupt function 35h to find the
- mov al, 01Ch ; current location of the timer interrupt
- int msdos ; routine. Save that location in
- mov intvector, bx ; [intvector].
- mov intvector+2, es
-
- push cs ; Point the timer interrupt
- pop ds ; to my program using DOS
- mov dx, offset int18_routine ; interrupt function 25h
- mov ah, 025h
- mov al, 01Ch
- int msdos
-
- mov dx, offset veryend ; terminate and stay in
- int terminate_stay_resident ; memory using DOS int. 27h
-
-
-
- ;------------------------------ ROUTINES --------------------------------
-
- int18_routine: ; this routine is called 18.2 times/second
- pushall ; Save all the registers and the flags.
-
- inc cs:counter2 ; this counter is used to
- cmp cs:counter2, 1092 ; display time once/minute
- jne int18_cont1
- mov cs:counter2, 0
- call showtime
-
- int18_cont1:
- inc cs:counter1 ; this counter is used to check
- cmp cs:counter1, 9 ; the row color twice/second
- jne exit
- mov cs:counter1, 0
- call checkrow
- cmp cs:flag, 0
- je exit
- mov cs:counter2, 1091 ; make time display next timer tick
-
- exit:
- popall ; restore all the registers and flags
-
- jmp dword ptr cs:[intvector] ; branch to the original
- ; timer interrupt routine
-
- ;--------------------------------------------------------------------------
-
- checkrow: ; this routine is called twice/second
- mov ah, 0Fh ; see what video mode we are in
- int screen
- cmp al, 3
- ifr a <jmp checkrow_ret> ; and don't print if in graphics mode
- cmp cs:mode, al ; see if the mode changed
- je short check_cont0
- mov cs:attribute, 0 ; and make it redraw if changed
- mov cs:mode, al ; by making the color-check part fail
-
- check_cont0:
- mov ah, 0Fh ; save the cursor in the [si] reg
- int screen
- mov bl, al ; save the mode in [bl]
- mov ah, 3
- int screen
- mov si, dx
-
- cmp cs:screen_page, bh ; if the page being viewed changes,
- je check_cont1 ; be sure to keep up with it.
- mov cs:screen_page, bh ; change the attribute to 0
- mov cs:attribute, 0 ; so the time will be redrawn
-
- check_cont1:
- mov di, 0 ; to indicate 80 column mode, [di]=0
- cmp bl, 2
- ifr b <mov di, 1> ; to indicate 40 column mode, [di]=1
-
- mov ah, 2 ; put the cursor at the end of the 26th
- mov dh, 25 ; line and see if there is an 'm' there.
- mov dl, 79 ; if not, then something must have
- cmp di, 1 ; erased the screen. set cs:attribute
- ifr e <mov dl, 39> ; to 0 so the next little bit will catch it
- int screen ; and redraw the bottom line
- mov ah, 8
- int screen
- cmp al, 'm'
- ifr ne <mov cs:attribute, 0>
-
- mov ah, 2 ; set cursor to y=24, x=end-of-row
- mov dh, 24
- ; mov dl, 0 ; uncomment this and comment-out the next
- mov dl, 79 ; three lines if you want x=start-of-row
- cmp di, 1
- ifr e <mov dl, 39>
- int screen
- mov ah, 8 ; read the color there
- int screen
- cmp cs:attribute, ah ; leave now if its the same
- je checkrow_exit_fine
- mov cs:attribute, ah ; else save the new color and change screen
- mov bl, ah ; save the color in [bl]
- mov ah, 2 ; set the cursor to the 26th line, 1st pos.
- mov dh, 25
- mov dl, 0
- int screen
- mov al, ' ' ; and print spaces across the 26th row
- mov cx, 80
- cmp di, 1
- ifr e <mov cx, 40>
- mov ah, 9
- int screen
-
- checkrow_exit_reshow:
- mov cs:flag, 1
- jmp short checkrow_exit
-
- checkrow_exit_fine:
- mov cs:flag, 0
-
- checkrow_exit:
- mov ah, 0Fh ; restore the cursor position
- int screen
- mov ah, 02
- mov dx, si ; get position from [si]
- int screen
-
- checkrow_ret:
- ret
-
- ;--------------------------------------------------------------------------
-
- showtime: ; this is called once/minute, and when
- ; the screen color changes.
- mov ah, 0Fh ; see what video mode we are in
- int screen
- cmp al, 3
- ifr a <jmp showtime_exit> ; and don't print if in graphics mode
-
- call click ; make a nice 'tick' sound
-
- mov ah, 0
- int time_of_day
-
- mov ax, dx ; divide ticks by 91
- mov dx, cx
- mov bx, 91
- div bx
-
- mov cx, dx ; and save the remainder in [cx]
-
- mov bx, 5 ; multiply result by 5
- mul bx
- mov cs:count, ax
- mov cs:count+2, dx ; save the result in [count]
-
- mov ax, cx ; divide the remainder (saved in [cx])
- mov dx, 0 ; by 18. This is the same as dividing by
- mov bx, 18 ; 18.2. I can't divide by 18 first because
- div bx ; at midnight this would give me a result
- ; greater than 0FFFFh. The margin of error
- ; is small. 32 seconds at midnight, less
- ; earlier in the day.
-
- add ax, cs:count ; add the result into [count] then save.
- mov cs:count, ax ; [count] now holds the total number of
- ; elapsed seconds since midnight (DOS).
-
- mov ax, cs:count ; divide the secs-since-midnight by 3600
- mov dx, cs:count+2 ; to get the hours since the start of the day
- mov bx, 3600
- div bx ; hours are now in [AL]. remainder
- mov cs:hours, al ; is in [DL]
-
- mov ax, dx ; divide the remainder by 60 to get the
- mov bl, 60 ; minutes since the start of the hour
- div bl
- mov cs:mins, al ; is in [AH]
-
- mov cs:secs, ah ; seconds are the remainder from above.
- ; [hours] now has the current hour in
- ; military format. [mins] has the current
- ; minutes. [secs] the current seconds.
-
-
-
- mov ah, 0Fh ; get current screen info
- int screen
- mov bl, al ; save the mode in [bl]
- mov ah, 3
- int screen
- mov si, dx ; save the cursor position in [si]
-
- mov dl, 72 ; set up x-pos to print time at. 40cols=32
- cmp bl, 2 ; 80cols=72.
- ifr b <mov dl, 32>
-
- mov bh, cs:screen_page ; set cursor position, y=26, x=[dl] reg.
- mov ah, 2
- mov dh, 25
- int screen
-
- mov dx, 03d4h ; make the screen 26 lines long
- mov al, 6 ; this is done by setting register #6 of the
- out dx, al ; CGA card to 26. It is possible to get
- mov dx, 03d5h ; as many as 29 rows of text with a CGA.
- mov al, 26
- out dx, al
-
- mov al, cs:hours ; show the time in standard format (AM/PM)
- mov di, 'a' ; set the [di] reg to 'a'
- cmp al, 12
- jbe show_cont1
- sub al, 12 ; subtract 12 from hours, and change [di]
- mov di, 'p' ; to 'p' if it is afternoon
- show_cont1:
- cmp al, 10 ; if there is only 1 digit in the hours
- jae show_cont2 ; (1:00-9:00) then don't print a leading
- mov ah, al ; zero, so we have to call shownib instead
- mov al, ' ' ; of show byte.
- call display_al
- mov al, ah
- call conv
- call shownib
- jmp short show_cont3
- show_cont2:
- call conv ; here the hours are between 10:00 and 12:00
- call showbyte ; so print the whole byte.
- show_cont3:
- mov al, ':' ; display a colon
- call display_al
- mov al, cs:mins ; display the minutes, leading zeros are
- call conv ; neccessary.
- call showbyte
- ; mov al, ':' ; un-comment this to display the seconds.
- ; call display_al ; you must also then change the position
- ; mov al, cs:secs ; where the time is printed on the line, and
- ; call conv ; must change the cs:counter2 check so the
- ; call showbyte ; routine is called more frequently.
- mov al, ' '
- call display_al ; here we display either ' am' or ' pm'
- mov ax, di
- call display_al
- mov al, 'm'
- call display_al
-
- mov ah, 0Fh ; restore the cursor position
- int screen
- mov ah, 02
- mov dx, si ; get position from [si]
- int screen
-
- showtime_exit:
- ret
-
- ;--------------------------------------------------------------------------
-
- conv: ; in: [al] contains the number to convert.
- push bp ; it must be less than 063h hex. out:
- push cx ; [al] is now converted. [ah] is destroyed
-
- mov bp, 0 ; use the DAA operand to add up the value of
- mov ah, al ; the lower 7 bits of [al] and save the
- mov al, 0 ; result in [al]. Refer to [convtable].
- mov cx, 7
- convloop:
- shr ah, 1
- jnc conv_cont1
- mov bl, cs:[bp+convtable]
- add al, bl
- daa
- conv_cont1:
- inc bp
- loop convloop
-
- conv_exit:
- mov ah, al
- pop cx
- pop bp
- ret
-
- ;--------------------------------------------------------------------------
-
-
- showword: ;This routine displays a word (AX)
- push ax
- push cx
- mov cl,8
- shr ax,cl
- call showbyte
- pop cx
- pop ax
-
- showbyte: ;This routine displays a byte (AL)
- push ax
- push cx
- mov cl,4
- shr al,cl
- call shownib
- pop cx
- pop ax
-
- shownib: ;This routine displays lower nibble(AL)
- push ax
- push dx
-
- and al, 0Fh
- mov dl,'0'
- cmp al,0Ah ;Hm.. need higher OR value? for hex digit
- jl show_c1
- mov dl,('A'-10)
-
- show_c1:
- add dl,al
- mov al, dl
- call display_al
- pop dx
- pop ax
- ret
-
- display_al:
- push ax ;This routines displays an ascii byte (AL)
- push bx
- push bp
- pushf
-
- push ax
- mov ah, 0Fh
- int screen
- mov ah, 08h
- int screen
- mov bl, al
- pop ax
- mov ah, 0Eh
- int screen
-
- popf
- pop bp
- pop bx
- pop ax
- ret
-
- ;--------------------------------------------------------------------------
-
- click: ; IN=none, OUT=none, all regs preserved.
- push ax
- push cx
-
- mov al, 10110110b
- out timer+3, al
- mov ax, 0777h ; this is the frequency of the tone
- out timer+2, al
- mov al, ah
- out timer+2, al
- in al, port_b
- mov ah, al
- or al, 03h
- out port_b, al
- mov cx, 0018h ; this is the duration of the tone
- loop $
- mov al, ah
- out port_b, al
-
- pop cx
- pop ax
- ret
-
-
- ;-------------------------------- ENDS ----------------------------------
-
- db 0 ; this is here for the DOS terminate-and-
- veryend: ; stay-resident function to work properly.
- code ends
- end start
- ;------------------------------ ROUTINES --------------------------------